#!/usr/bin/python3
import os
from .Entity import Entity
from .Biz_Method import Biz_Method
from utils import My_Util2


class Service_Impl(Biz_Method):
    """
    业务实现类
    """

    def __init__(self, context, entity: Entity) -> None:
        self.context = context
        self.entity: Entity = entity
        self.prefix: str = self.entity.table_name.split("_")[0].lower()
        self.my_util2 = My_Util2.My_Util(self.context)

    def code_includes(self):
        package = self.entity.package
        prefix = self.entity.table_name.split("_")[0].lower()
        entity_name = self.entity.name

        includes = list()
        _sort = self.entity.has_sort()
        _status = self.entity.has_status()

        includes.append(
            f"""import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;"""
        )
        includes.append(f"""import com.baomidou.mybatisplus.core.toolkit.Wrappers;""")
        includes.append(
            f"""import com.baomidou.mybatisplus.extension.plugins.pagination.Page;"""
        )
        includes.append(f"""import {package}.internal.entity.{entity_name};""")
        includes.append(f"""import {package}.internal.lambdas.Fn;""")
        includes.append(f"""import {package}.internal.transaction.BusinessException;""")
        includes.append(f"""import {package}.internal.transaction.Tx;""")
        includes.append(f"""import {package}.internal.util.MyUtil;""")
        includes.append(f"""import {package}.internal.validation.MyAssert;""")
        includes.append(f"""import {package}.{prefix}.bo.{entity_name}BO;""")
        if _sort:
            includes.append(f"""import {package}.internal.model.SwapBO;""")
        includes.append(
            f"""import {package}.{prefix}.query.exists.{entity_name}Exists;"""
        )
        includes.append(f"""import {package}.{prefix}.bo.{entity_name}UpdateBO;""")
        includes.append(f"""import {package}.{prefix}.mapper.{entity_name}Mapper;""")
        includes.append(f"""import {package}.{prefix}.query.{entity_name}QueryInfo;""")
        includes.append(f"""import {package}.{prefix}.service.I{entity_name}Service;""")
        includes.append(f"""import {package}.{prefix}.vo.{entity_name}VO;""")
        includes.append(f"""import com.we7.platform.base.server.IServerImpl;""")
        if _status:
            includes.append(f"""import com.we7.platform.base.util.ThreadContext;""")
        if _sort:
            includes.append(f"""import com.we7.platform.base.sql.MySqlFunction;""")
        includes.append(f"""import lombok.RequiredArgsConstructor;""")
        includes.append(f"""import org.springframework.stereotype.Service;""")
        includes.append(f"""import org.springframework.util.CollectionUtils;""")
        includes.append(f"""import java.util.ArrayList;""")
        if _sort:
            includes.append(f"""import java.util.Arrays;""")
        if _status:
            includes.append(f"""import java.util.Date;""")
        includes.append(f"""import java.util.List;""")
        includes.append(f"""import java.util.Objects;""")
        includes = self.my_util2.sort_import_order(includes)
        return "\r".join(includes)

    def code_save(self):
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        comment = self.entity.comment

        if self.entity.has_status():
            status = f"""
        {object_name}.setStatus(true);"""
        else:
            status = ""
        return f"""
    @Override
    public boolean save({entity_name}BO {object_name}BO) throws BusinessException {"{"}
        {entity_name}Exists {object_name}Exists = new {entity_name}Exists();
        {object_name}Exists.setWaitDelete(false);
        MyUtil.copyProperties({object_name}BO, {object_name}Exists);
        MyAssert.isTrue(!this.exists({object_name}Exists), "{comment}记录已存在");
        {entity_name} {object_name} = new {entity_name}();
        MyUtil.copyProperties({object_name}BO, {object_name});{status}
        return tx.doing((status) ->
                super.save({object_name})
        );
    {"}"}"""

    def code_remove_list(self):
        entity_name = self.entity.name
        comment = self.entity.comment
        return f"""
    @Override
    public boolean remove{entity_name}ByIds(String ids) throws BusinessException {"{"}
        MyAssert.hasLength(ids, "{comment}主键列表不能为空");
        List<Long> idList = MyUtil.splitIds(ids);
        MyAssert.isTrue(!CollectionUtils.isEmpty(idList), "{comment}主键列表不能为空");
        List<{entity_name}> oldList = super.listByIds(idList);
        MyAssert.isTrue(!CollectionUtils.isEmpty(oldList), "{comment}记录不存在");
        oldList.forEach(old -> old.setWaitDelete(true));
        return tx.doing((status) ->
                super.updateBatchById(oldList)
        );
    {"}"}"""

    def code_update(self):
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        comment = self.entity.comment
        return f"""
    @Override
    public boolean update{entity_name}ById({entity_name}UpdateBO {object_name}UpdateBO) throws BusinessException {"{"}
        MyAssert.notNull({object_name}UpdateBO.getId(), "{comment}主键不能为空");
        {entity_name} oldObj = super.getById({object_name}UpdateBO.getId());
        {entity_name} newObj = new {entity_name}();
        MyUtil.copyProperties({object_name}UpdateBO, newObj);
        UpdateWrapper<{entity_name}> updateWrapper = MyUtil.builUpdateWrapper({entity_name}.class, oldObj, newObj);
        return tx.doing((status) -> super.update(updateWrapper));
    {"}"}"""

    def code_nullify_or_revert(self):
        if not self.entity.has_status():
            return None
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        comment = self.entity.comment
        return f"""
    @Override
    public boolean nullifyOrRevertByIds(String ids) throws BusinessException {"{"}
        MyAssert.hasLength(ids, "{comment}主键不能为空");
        List<Long> idList = MyUtil.splitIds(ids);
        List<{entity_name}> {object_name}List = super.listByIds(idList);
        MyAssert.isTrue(!CollectionUtils.isEmpty({object_name}List), "{comment}记录不存在");
        {object_name}List.forEach({object_name} -> {"{"}
            if ({object_name}.getStatus()) {"{"}
                {object_name}.setNullifierId(ThreadContext.getUserId());
                {object_name}.setNullifierName(ThreadContext.getUserName());
                {object_name}.setNullifierDate(new Date());
            {"}"}
            {object_name}.setStatus(!{object_name}.getStatus());
        {"}"});
        return tx.doing((status) ->
                super.updateBatchById({object_name}List)
        );
    {"}"}"""

    def code_swap(self):
        if not self.entity.has_sort():
            return None
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        comment = self.entity.comment
        return f"""
    @Override
    public boolean swap{entity_name}(SwapBO swapBO) throws BusinessException {"{"}
        {entity_name} {object_name} = super.getById(swapBO.getId());
        {entity_name} another = super.getById(swapBO.getAnother());
        MyAssert.notNull({object_name}, "{comment}记录不存在");
        MyAssert.notNull(another, "{comment}记录不存在");
        Integer sort = {object_name}.getSortNumber();
        Integer sortAnother = another.getSortNumber();
        {object_name}.setSortNumber(sortAnother);
        another.setSortNumber(sort);
        List<{entity_name}> {object_name}List = Arrays.asList({object_name}, another);
        return tx.doing((status) ->
                super.updateBatchById({object_name}List)
        );
    {"}"}"""

    def code_get(self):
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        comment = self.entity.comment
        return f"""
    @Override
    public {entity_name}VO getById(Long id) {"{"}
        MyAssert.notNull(id, "{comment}主键不能为空");
        {entity_name} {object_name} = super.getById(id);
        MyAssert.notNull({object_name}, "{comment}记录不存在");
        {entity_name}VO {object_name}VO = new {entity_name}VO();
        MyUtil.copyProperties({object_name}, {object_name}VO);
        return {object_name}VO;
    {"}"}"""

    def code_get_by_condition(self):
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        comment = self.entity.comment
        return f"""
    @Override
    public {entity_name}VO getByCondition({entity_name}Exists {object_name}Exists) {"{"}
        MyAssert.isTrue(!{object_name}Exists.isNull(), "查询条件不能全部为空");
        {entity_name} condition = new {entity_name}();
        MyUtil.copyProperties({object_name}Exists, condition);
        LambdaQueryWrapper<{entity_name}> queryWrapper = new LambdaQueryWrapper<>();
        long count = super.count(queryWrapper);
        if (count > 1) {"{"}
            MyAssert.isTrue(false, "找到多个符合条件的{comment}");
        {"}"} else if (count == 0) {"{"}
            MyAssert.isTrue(false, "未找到符合条件的{comment}");
        {"}"}
        queryWrapper.setEntity(condition);
        {entity_name} {object_name} = super.getOne(queryWrapper);
        MyAssert.notNull({object_name}, "未找到符合条件的{comment}");
        {entity_name}VO {object_name}VO = new {entity_name}VO();
        MyUtil.copyProperties({object_name}, {object_name}VO);
        return {object_name}VO;
    {"}"}"""

    def code_get_by_condition_columns(self):
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        comment = self.entity.comment
        return f"""
    @Override
    public {entity_name}VO getByCondition({entity_name}Exists {object_name}Exists, List<Fn<{entity_name}>> columns) {"{"}
        MyAssert.isTrue(!{object_name}Exists.isNull(), "条件不能全部为空");
        {entity_name} condition = new {entity_name}();
        MyUtil.copyProperties({object_name}Exists, condition);
        QueryWrapper<{entity_name}> selectQueryWrapper = new QueryWrapper<>(condition);
        if (CollectionUtils.isEmpty(columns)) {"{"}
            selectQueryWrapper.select(MyUtil.getColumnNameListExcept({entity_name}.class, null));
        {"}"} else {"{"}
            selectQueryWrapper.select(MyUtil.getColumnNameListInclude({entity_name}.class, columns));
        {"}"}
        LambdaQueryWrapper<{entity_name}> queryWrapper = selectQueryWrapper.lambda();
        long count = super.count(Wrappers.lambdaQuery(condition));
        if (count > 1) {"{"}
            MyAssert.isTrue(false, "找到多个符合条件的对象");
        {"}"} else if (count == 0) {"{"}
            MyAssert.isTrue(false, "未找到符合条件的对象");
        {"}"}
        {entity_name} {object_name} = super.getOne(queryWrapper);
        MyAssert.notNull({object_name}, "未找到符合条件的对象");
        {entity_name}VO {object_name}VO = new {entity_name}VO();
        MyUtil.copyProperties({object_name}, {object_name}VO);
        return {object_name}VO;
    {"}"}"""

    def code_page(self):
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        if self.entity.has_status():
            status_condition = f"""
        if (Objects.nonNull({object_name}QueryInfo.getStatus())) {"{"}
            queryWrapper.eq({entity_name}::getStatus, {object_name}QueryInfo.getStatus());
        {"}"}
"""
        else:
            status_condition = None
        return f"""
    @Override
    public Page<{entity_name}VO> getPageByQueryInfo({entity_name}QueryInfo {object_name}QueryInfo, Page<{entity_name}> p) {"{"}
        LambdaQueryWrapper<{entity_name}> queryWrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull({object_name}QueryInfo.getWaitDelete())) {"{"}
            queryWrapper.eq({entity_name}::getWaitDelete, {object_name}QueryInfo.getWaitDelete());
        {"}"}{status_condition if status_condition is not None else ''}
        Page<{entity_name}> page = super.page(p, queryWrapper);
        Page<{entity_name}VO> pageVO = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        List<{entity_name}> records = page.getRecords();
        List<{entity_name}VO> recordsVO = new ArrayList<>();
        records.forEach(record -> {"{"}
            {entity_name}VO {object_name}VO = new {entity_name}VO();
            MyUtil.copyProperties(record, {object_name}VO);
            recordsVO.add({object_name}VO);
        {"}"});
        pageVO.setRecords(recordsVO);
        return pageVO;
    {"}"}"""

    def code_list(self):
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        return f"""
    @Override
    public List<{entity_name}VO> list({entity_name}Exists {object_name}Exists) {"{"}
        {entity_name} condition = new {entity_name}();
        MyUtil.copyProperties({object_name}Exists, condition);
        LambdaQueryWrapper<{entity_name}> queryWrapper = new LambdaQueryWrapper<>(condition);
        if (!CollectionUtils.isEmpty({object_name}Exists.getIdList())) {"{"}
            queryWrapper.in({entity_name}::getId, {object_name}Exists.getIdList());
        {"}"}
        List<{entity_name}> {object_name}List = super.list(queryWrapper);
        List<{entity_name}VO> {object_name}VOList = new ArrayList<>();
        {object_name}List.forEach(record -> {"{"}
            {entity_name}VO {object_name}VO = new {entity_name}VO();
            MyUtil.copyProperties(record, {object_name}VO);
            {object_name}VOList.add({object_name}VO);
        {"}"});
        return {object_name}VOList;
    {"}"}"""

    def code_list_columns(self):
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        return f"""
    @Override
    public List<{entity_name}VO> list({entity_name}Exists {object_name}Exists,
            List<Fn<{entity_name}>> columns) {"{"}
        {entity_name} condition = new {entity_name}();
        MyUtil.copyProperties({object_name}Exists, condition);
        LambdaQueryWrapper<{entity_name}> queryWrapper;
        if (!CollectionUtils.isEmpty(columns)) {"{"}
            QueryWrapper<{entity_name}> columnQueryWrapper = new QueryWrapper<>(condition);
            columnQueryWrapper.select(MyUtil.getColumnNameListInclude({entity_name}.class, columns));
            queryWrapper = columnQueryWrapper.lambda();
        {"}"} else {"{"}
            queryWrapper = new LambdaQueryWrapper<>(condition);
        {"}"}
        if (!CollectionUtils.isEmpty({object_name}Exists.getIdList())) {"{"}
            queryWrapper.in({entity_name}::getId, {object_name}Exists.getIdList());
        {"}"}
        List<{entity_name}> {object_name}List = super.list(queryWrapper);
        List<{entity_name}VO> {object_name}VOList = new ArrayList<>();
        {object_name}List.forEach(record -> {"{"}
            {entity_name}VO {object_name}VO = new {entity_name}VO();
            MyUtil.copyProperties(record, {object_name}VO);
            {object_name}VOList.add({object_name}VO);
        {"}"});
        return {object_name}VOList;
    {"}"}"""

    def code_next_sort(self):
        if not self.entity.has_sort():
            return None
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        return f"""
    @Override
    public Integer getNextSortNumber() {"{"}
        {entity_name} {object_name} = getOne(Wrappers.<{entity_name}>lambdaQuery()
                .eq({entity_name}::getWaitDelete, false)
                .orderByDesc({entity_name}::getSortNumber)
                .last(MySqlFunction.LIMIT_ONE)
        );

        return Objects.nonNull({object_name}) ? {object_name}.getSortNumber() + 1 : 1;
    {"}"}"""

    def code_exists(self):
        entity_name = self.entity.name
        object_name = entity_name[:1].lower() + entity_name[1:]
        return f"""
    @Override
    public boolean exists({entity_name}Exists {object_name}Exists) {"{"}
        MyAssert.isTrue(!{object_name}Exists.isNull(), "条件不能全部为空");
        {entity_name} condition = new {entity_name}();
        MyUtil.copyProperties({object_name}Exists, condition);
        LambdaQueryWrapper<{entity_name}> queryWrapper = new LambdaQueryWrapper<>(condition);
        return super.count(queryWrapper) > 0;
    {"}"}"""

    def code(self):
        author = self.entity.author
        package = self.entity.package
        entity_name = self.entity.name
        comment = self.entity.comment
        prefix = self.prefix

        includes = self.code_includes()

        codes = list()
        save = self.code_save()
        codes.append(save)
        remove_list = self.code_remove_list()
        codes.append(remove_list)
        update = self.code_update()
        codes.append(update)
        nullify_or_revert = self.code_nullify_or_revert()
        if nullify_or_revert is not None:
            codes.append(nullify_or_revert)
        swap = self.code_swap()
        if swap is not None:
            codes.append(swap)
        get = self.code_get()
        codes.append(get)
        # get_by_condition = self.code_get_by_condition()
        # codes.append(get_by_condition)
        # get_by_condition_columns = self.code_get_by_condition_columns()
        # codes.append(get_by_condition_columns)
        page = self.code_page()
        codes.append(page)
        code_list = self.code_list()
        codes.append(code_list)
        # code_list_columns = self.code_list_columns()
        # codes.append(code_list_columns)
        next_sort = self.code_next_sort()
        if next_sort is not None:
            codes.append(next_sort)
        exists = self.code_exists()
        codes.append(exists)
        codes = "\r".join(codes)

        return f"""package {package}.{prefix}.service.impl;

{includes}

/**
 * <p>
 * {comment}业务接口实现类
 * </p>
 *
 * @author {author}
 */
@Service
@RequiredArgsConstructor
public class {entity_name}ServiceImpl extends IServerImpl<{entity_name}Mapper, {entity_name}> implements I{entity_name}Service {"{"}

    private final Tx tx;
{codes}
{"}"}
"""

    def save_file(self, dir):
        _target_dir = os.path.join(dir, self.prefix, "service", "impl")
        if not os.path.exists(_target_dir):
            os.makedirs(_target_dir)
        with open(
            os.path.join(_target_dir, "{}ServiceImpl.java".format(self.entity.name)),
            mode="w",
            encoding="utf-8",
        ) as f:
            f.write(self.code())
